<?php
class SqlAlias {
	private $orig;
	private $alias;
	
	public function __construct($o, $a) {
		$this->orig = $o;
		$this->alias = $a;
	}
	
	public function getOrig() {
		return $this->orig;
	}
	
	public function getAlias() {
		return $this->alias;
	}
	
	public function setOrig($o) {
		$this->orig = $o;
	}
	
	public function setAlias($a) {
		$this->alias = $a;
	}
	
	public function sqlize() {
		return $this->alias.".".$this->orig;
	}
}

class DeltaValue {
	const PLUS = "+";
	const MINUS = "-";
	
	private $operand;
	private $value;
	
	public function __construct($value, $operand = DeltaValue::PLUS) {
		$this->operand	= $operand;
		$this->value	= $value;
	}
	
	public function getOperand() {return $this->operand;}
	public function getValue() {return $this->value;}
}

class SqlCondition {
	/*
	 * Available operators should be:
	 */
	const LARGERTHAN 	= ">";
	const NOLESSTHAN	= ">=";
	const EQUAL 		= "=";
	const NOTEQUAL		= "<>";
	const LESSTHAN 		= "<";
	const NOLARGERTHAN	= "<=";
	const LIKE 			= " LIKE ";
	
	/*
	 * Relations:
	 */
	const _AND = "AND";
	const _OR  = "OR";
	
	private $key;
	private $operator;
	private $value;
	
	public function __construct($key = 'id', $operator = SqlCondition::EQUAL, $value = 1) {
		if ($key instanceof SqlAlias)
			$this->key 		= mysql_escape_string($key->sqlize());
		else
			$this->key 		= mysql_escape_string($key);
		$this->operator = mysql_escape_string($operator);
		
		if ($value instanceof SqlAlias)
			$this->value 	= mysql_escape_string($value->sqlize());
		else
			$this->value 	= mysql_escape_string($value);
	}
	
	public function getKey() {
		return $this->key;
	}
	public function getOperator() {
		return $this->operator;
	}
	public function getValue() {
		return $this->value;
	}
}

class SqlConstraint {
	/*
	 * This class identifies GROUP BY, ORDER BY.
	 */
	
	// verbs.
	const GROUPBY = " GROUP BY ";
	const ORDERBY = " ORDER BY ";
		
	private $constraint;
	private $col;
	
	public function __construct($constraint = NULL, $col = NULL) {
		$this->constraint 	= mysql_escape_string($constraint);
		$this->col 			= mysql_escape_string($col);
	}
	
	public function sqlize() {
		$ret = "";
		if ($this->constraint != NULL && $this->constraint != "") {
			$ret = $ret . $this->constraint;
		}
		
		if ($this->col != NULL && $this->col != "") {
			$ret = $ret . $this->col;
		}
				
		return $ret;
	}
}

class SqlLimit {
	/*
	 * This class identifies LIMIT.
	 */
		
	// parameters.
	private $offset;
	private $length;
	
	public function __construct($offset, $length = NULL) {
		$this->offset = mysql_escape_string($offset);
		$this->length = mysql_escape_string($length);
	}
	
	public function sqlize() {
		$ret = " ";
		if ($this->offset != NULL && $this->offset != "") {
			$ret = $ret."LIMIT ";
			$ret = $ret . $this->offset;
		} else {
			return " ";
		}
		
		if ($this->length != NULL && $this->length != "") {
			$ret = $ret . ",";
			$ret = $ret . $this->length;
		}
		
		return $ret;
	}
}

class SqlSort {
	/*
	 * This class identifies LIMIT.
	 */
	const ASC  = "ASC";
	const DESC = "DESC";
	
	// parameters.
	private $sort;
	
	public function __construct($sort = NULL) {
		$this->sort = mysql_escape_string($sort);
	}	
	
	public function sqlize() {
		$ret = " ";
		if ($this->sort != NULL && $this->sort != "") {
			$ret = $ret.$this->sort;
		}
				
		return $ret;
	}
}

class SqlCondList {
	private $conditions;
	private $relations;
	private $constraints;
	private $sort;
	private $limit;
	private $bracket_index;
	private $start_brackets;
	private $end_brackets;
	
	public function __construct() {
		$this->conditions = array(); 
		$this->relations = array();
		$this->constraints = array();
		$this->brackets = array();
		$this->sort = NULL;	
		$this->limit = NULL;
		$this->bracket_index = 0;		
	}
	
	public function add_start_bracket() {
		if (isset($this->brackets[$this->bracket_index])) {
			$tmp = $this->brackets[$this->bracket_index];
			$this->brackets[$this->bracket_index] = $tmp.' ( ';
		} else {
			$this->brackets[$this->bracket_index] = ' ( ';
		}
	}
	
	public function add_end_bracket() {
		if (isset($this->brackets[$this->bracket_index])) {
			$tmp = $this->brackets[$this->bracket_index];
			$this->brackets[$this->bracket_index] = $tmp.' ) ';
		} else {
			$this->brackets[$this->bracket_index] = ' ) ';
		}
	}
	
	public function add_condition($c) {
		$this->conditions[] = $c;
		$this->bracket_index++;
	}
	
	public function add_relation($r) {
		$this->relations[] = $r;
		$this->bracket_index++;
	}
	
	public function add_constraint($c) {
		$this->constraints[] = $c;
	}
	
	/*
	 * Overwrite the limit part.
	 */
	public function add_limit($l) {
		$this->limit = $l;
	}
	
	public function add_sort($sort) {
		$this->sort = $sort;
	}
	
	public function get_cnt_of_condition() {
		return count($this->conditions);
	}
	
	public function is_empty_condition() {
		return (count($this->conditions) == 0);
	}
	
	public function sqlize() {		
		// Generate the conditions part of the update SQL instruction
		$where = ' '; // Ensure the whitespace exists on the beginning.
		if (count($this->conditions)) {
			$keys = array_keys($this->conditions);
			$where = $where."where ";
			$i = 0;
			foreach ($keys as $k) {
				if (array_key_exists($i, $this->brackets))
					$where .= $this->brackets[$i];
				
				$c = $this->conditions[$k];
				if (gettype($c) == gettype(new SqlCondition())) {
					$where = $where.$c->getKey().$c->getOperator().'"'.$c->getValue().'" ';
				}
				$i++;
				
				if (array_key_exists($i, $this->brackets))
					$where .= $this->brackets[$i];
				
				if (array_key_exists($k, $this->relations)) {
					$r = $this->relations[$k];
					$where = $where.$r." ";
				}
				
				$i++;
			}
			// For the possible ending brackets.
			if (array_key_exists($i, $this->brackets))
					$where .= $this->brackets[$i];
		}
		
		if (count($this->constraints)) {
			$where = $where." ";
			foreach ($this->constraints as $c) {
				if (gettype($c) == gettype(new SqlConstraint())) {
					$where = $where.$c->sqlize().' ';
				}
			}
		}
		
		if ($this->sort != NULL)
			$where = $where." ".$this->sort->sqlize();
		
		if ($this->limit != NULL) {
			$where = $where." ".$this->limit->sqlize();
		}
		
		return $where;
	}
}

class MySqlConnector {
	private $connection;
	private $queried_result;
	
	private $host;
	private $user_name;
	private $password;
	private $database;
	
	private $cleaned;
	private $errno;
	
	public function __construct($host, $user_name, $password, $database) {
		$this->host = $host;
		$this->user_name = $user_name;
		$this->password = $password;
		$this->database = $database;
		
		$cleaned = FALSE;
		$errno = NULL;
	}
	
	public function connect() {
		$this->errno = NULL;
		$this->GetMySQLConn2DB();
	}
	
	public function get_error() {
		return $this->errno;
	}
	
	public function execute($sql_instruction) {
		$this->errno = NULL;
		$this->GetDataStoreFromConn($sql_instruction);
		return $this->queried_result;
	}
	
	/*
	 * Note, you can only get the auto-incremented ID after your inserting operation.
	 * If no auto-incremented ID is generated, 0 is returned.
	 */
	public function get_auto_incremented_id() {
		$ret = mysql_insert_id($this->connection);
		if ($ret == FALSE)
			return DbError::NO_MYSQL_CONNECTION_AVAILABLE;
		else if ($ret == 0)
			return DbError::NO_AUTOINCREMENTED_ID_GENERATED;
		else
			return $ret; // Generated ID is returned.
	}
	
	public function cleanup() {
		if (!$this->cleaned) {
			$this->FreeQueriedDataStore();
			//$this->CloseMySQLConn();
			
			$this->cleaned = TRUE;
		}
	}
	
	public function __destruct() {
		$this->cleanup();
	}
	
	private function GetMySQLConn2DB()
	{
		$this->connection = @mysql_connect($this->host, $this->user_name, $this->password);
		//$this->connection = ConnSingleton::getConnection($this->host, $this->user_name, $this->password);
		//echo "<p>".$this->connection;
		if(!$this->connection)
		{
			//echo 'MySQL ERROR: '.mysql_error();
			$this->errno = mysql_errno();
		//	return NULL;
		}
		$stat = @mysql_select_db($this->database, $this->connection);
		if (!$stat)
		{
			//echo 'MySQL ERROR: '.mysql_error();
			$this->errno = mysql_errno();
		//	return NULL;
		}
	}
		
	private function GetDataStoreFromConn($sql_instruction)
	{
		// Free the datastore if needed first.
		$this->FreeQueriedDataStore();
		$this->queried_result = @mysql_query($sql_instruction);
		if(!$this->queried_result)
		{
			//echo 'MySQL ERROR: '.mysql_error();
			$this->errno = mysql_errno();
			$this->queried_result = NULL;
		}
	}

	private function FreeQueriedDataStore()
	{
		if (!is_resource($this->queried_result))
			return TRUE;
			
		$stat = @mysql_free_result($this->queried_result);
		if(!$stat)
		{
			//echo 'MySQL ERROR: '.mysql_error();
			$this->errno = mysql_errno();
		}
	
		return $stat;
	}

	private function CloseMySQLConn()
	{
		$stat = @mysql_close($this->connection);
		if(!$stat)
		{
			//echo 'MySQL ERROR: '.mysql_error();
			$this->errno = mysql_errno();
		}
		return $stat;
	}	
}

class ConnSingleton
{
    static private $connection = NULL;

	static private $host		= NULL;
	static private $user_name	= NULL;
	static private $password	= NULL;
    private function __construct($host, $u_name, $pwd){}

	private function __destruct() {
		//if (ConnSingleton::$connection != NULL) {
		//	mysql_close(ConnSingleton::$connection);	
		//}
	}

    static public function getConnection($host, $user_name, $password) {
        if (self::$connection == NULL || 
			self::$host != $host ||
			self::$user_name != $user_name ||
			self::$password != $password) {
			
			self::$host			= $host;
			self::$user_name	= $user_name;
			self::$password		= $password;
            self::$connection	= @mysql_connect($host, $user_name, $password);
        }

        return self::$connection;
    }
}
?>